package com.alg.local.gateway.util;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.Security;

/**
 * @author al
 * @date 2022/2/18 16:46
 * @description 对称加密工具类 CBC模式
 */
public class SymmetricEncryptionUtilCbc {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * IV是Base64后的，加密结果是Base64的
     */
    public static String encrypt(String key, String iv, String input) throws GeneralSecurityException {
        return Base64Util.encoder(encrypt(key.getBytes(StandardCharsets.UTF_8), Base64Util.decoder(iv),
                input.getBytes(StandardCharsets.UTF_8)));
    }

    /**
     * IV是16位的，加密结果是Base64的
     */
    public static String encryptBase64(String key, String iv, String input) throws GeneralSecurityException {
        return Base64Util.encoder(encrypt(key.getBytes(StandardCharsets.UTF_8), iv.getBytes(StandardCharsets.UTF_8),
                input.getBytes(StandardCharsets.UTF_8)));
    }

    /**
     * IV是16位的，加密结果是Hex的
     */
    public static String encryptHex(String key, String iv, String input) throws GeneralSecurityException {
        return Hex.toHexString(encrypt(key.getBytes(StandardCharsets.UTF_8), iv.getBytes(StandardCharsets.UTF_8),
                input.getBytes(StandardCharsets.UTF_8)));
    }

    public static byte[] encrypt(byte[] key, byte[] iv, byte[] input) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        IvParameterSpec ivps = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivps);
        return cipher.doFinal(input);
    }

    // --------------------

    /**
     * IV是Base64后的，解密入参是Base64的
     */
    public static String decrypt(String key, String iv, String input) throws GeneralSecurityException {
        return new String(decrypt(key.getBytes(StandardCharsets.UTF_8), Base64Util.decoder(iv),
                Base64Util.decoder(input)), StandardCharsets.UTF_8);
    }

    /**
     * IV是16位的，解密入参是Base64的
     */
    public static String decryptBase64(String key, String iv, String input) throws GeneralSecurityException {
        return new String(decrypt(key.getBytes(StandardCharsets.UTF_8), iv.getBytes(StandardCharsets.UTF_8),
                Base64Util.decoder(input)), StandardCharsets.UTF_8);
    }

    /**
     * IV是16位的，解密入参是Hex的
     */
    public static String decryptHex(String key, String iv, String input) throws GeneralSecurityException {
        return new String(decrypt(key.getBytes(StandardCharsets.UTF_8), iv.getBytes(StandardCharsets.UTF_8),
                Hex.decode(input)), StandardCharsets.UTF_8);
    }

    public static byte[] decrypt(byte[] key, byte[] iv, byte[] input) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        IvParameterSpec ivps = new IvParameterSpec(iv);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivps);
        return cipher.doFinal(input);
    }

    public static void main(String[] args) {
        String msg = "Hello";
        String key = "JlBMFV4CA0XkQHBF6VO1Ug==";
        String iv = "VXOXB/xJnG0xiRH/zSzxFQ==";

        try {
            byte[] encrypt = encrypt(key.getBytes(), Base64Util.decoder(iv), msg.getBytes());
            System.out.println(Hex.toHexString(encrypt));
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        }

    }

}
